package com.lxk.service.utils;

import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
@Component
public class SensitiveWordsHandler implements InitializingBean {

    private class TrieNode {
        //是否是关键词的结尾
        private boolean end = false;
        //当前节点下所有的子节点
        private Map<Character,TrieNode> subNodes = new HashMap<Character,TrieNode>();

        private void addSubNode(Character key,TrieNode node) {
            subNodes.put(key, node);
        }

        private TrieNode getSubNode(Character key) {
            return subNodes.get(key);
        }

        private boolean isKeywordEnd() {
            return end;
        }

        private void setKeywordEnd(boolean end) {
            this.end = end;
        }
    }

    private TrieNode rootNode = new TrieNode();

    private static final Logger logger = LoggerFactory.getLogger(SensitiveWordsHandler.class);
    @Override
    public void afterPropertiesSet() throws Exception {
        InputStream is = null;
        InputStreamReader read = null;
        BufferedReader bufferedReader = null;
        try{
            is = Thread.currentThread().getContextClassLoader().getResourceAsStream("SensitiveWords.txt");
            read = new InputStreamReader(is);
            bufferedReader = new BufferedReader(read);
            String lineTxt;
            while((lineTxt=bufferedReader.readLine())!=null){
                addWord(lineTxt.trim());
            }
        }catch(Exception e){
            logger.error("读取敏感词文件失败"+e.getMessage());
        }finally{
            if(ObjectUtils.isNotEmpty(bufferedReader)){
                bufferedReader.close();
            }
            if(ObjectUtils.isNotEmpty(read)){
                read.close();
            }
            if(ObjectUtils.isNotEmpty(is)){
                is.close();
            }
        }
    }

    private void addWord(String lineTxt){
        TrieNode tempNode = rootNode;
        for(int i = 0;i < lineTxt.length(); i++){
            Character c = lineTxt.charAt(i);
            if(isSymbol(c)){
                continue;
            }
            TrieNode node = tempNode.getSubNode(c);
            if(node==null){
                node = new TrieNode();
                tempNode.addSubNode(c, node);
            }
            tempNode = node;
            if(i==lineTxt.length()-1)
                tempNode.setKeywordEnd(true);
        }
    }

    /**
     * 非数字、字母和东亚文字范围
     * @param c
     * @return
     */
    private boolean isSymbol(char c){
        int ic = (int)c;
        return !CharUtils.isAsciiAlphanumeric(c)&&(ic<0x2E80||ic>0x9FFF);
    }

    public String filter(String text) {
        if(StringUtils.isBlank(text)){
            return text;
        }

        String replacement = "***";
        TrieNode tempNode = rootNode;
        int begin = 0;
        int position = 0;
        StringBuilder result = new StringBuilder();
        while(position<text.length()){
            char c = text.charAt(position);
            //判断字符是否正常内容
            if(isSymbol(c)){
                //非正常内容，判断是否在字典树起点
                if(tempNode==rootNode){
                    result.append(c);
                    ++begin;
                }
                //无论是否开始走字典树，当前位置都要移动，判断后面的
                ++position;
                continue;
            }
            tempNode = tempNode.getSubNode(c);
            if(tempNode==null){
                //如果当前字符不在字典树下一层
                result.append(c);
                position = begin+1;
                begin = position;
                tempNode = rootNode;
            }else if(tempNode.isKeywordEnd()){
                //发现敏感词
                result.append(replacement);
                position = position+1;
                begin = position;
                tempNode = rootNode;
            }else{
                ++position;
            }
        }
        result.append(text.substring(begin));
        return result.toString();
    }

    public static void main(String[] args) {
        SensitiveWordsHandler s = new SensitiveWordsHandler();
        s.addWord("色情");
        s.addWord("赌博");
        s.addWord("傻逼");
        System.out.println(s.filter("你是傻1吧！！！"));
    }

}
